<!--部门员工选择器-->
<template>
	<a-select v-model:value="selections" v-bind="options" class="dept-emp-select">
		<template #dropdownRender="{menuNode}">
			<div class="dept-emp-search-wrapper" @click.stop>
				<a-form-item-rest>
					<a-input v-model:value="keyword" allow-clear :placeholder="`请输入${onlyStore ? '门店' : '部门'}${onlyDept ? '' : '、人员'}名称搜索`" style="border-radius: 50px">
						<template #suffix>
							<search-outlined />
						</template>
					</a-input>
				</a-form-item-rest>
			</div>
			<div class="dept-emp-wrapper" @click.stop>
				<a-skeleton :loading="loadings.load" active :paragraph="{rows: 8}">
					<template v-if="flatDepts.length">
						<a-tree v-bind="deptTreeOptions" />
						<div v-if="!onlyDept" class="emp-container">
							<a-tree v-if="filterEmplyees.length" v-bind="empTreeOptions" />
							<a-empty v-else class="house-empty ant-empty-small" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
						</div>
					</template>
					<a-empty v-else class="house-empty ant-empty-small" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
				</a-skeleton>
			</div>
			<a-divider @click.stop />
			<a-space @click.stop>
				<a-button @click="clear">清空</a-button>
				<a-button type="primary" @click="confirm">确认</a-button>
			</a-space>
		</template>
	</a-select>
</template>

<script lang="ts" setup>
	import {computed, onMounted, reactive, ref, toRef, watch} from 'vue'
	import settingApi from 'yuxin-base/src/api/setting-api'
	import XEUtils from 'xe-utils'
	import {SearchOutlined} from '@ant-design/icons-vue'
	import {Department, Employee} from 'yuxin-base/src/types'
	import {DEFAULT_FIELD_NAME} from 'yuxin-base/src/constant'
	import {Empty} from 'ant-design-vue'
	import {useStore} from '@/store'
	import _ from 'lodash'
	const store = useStore()

	const props = defineProps<{
		// 员工id
		empId?: any
		// 部门id
		deptId?: any
		// 是否支持多选
		multiple?: boolean
		// 仅显示部门选择
		onlyDept?: boolean
		// 仅可以选择人员
		onlyEmp?: boolean
		// 仅显示门店
		onlyStore?: boolean
		// 占位提示
		placeholder?: string
		disabled?: boolean
		cache?: boolean
	}>()

	const options = reactive<any>({
		open: false,
		options: [],
		allowClear: true,
		maxTagCount: 'responsive',
		fieldNames: DEFAULT_FIELD_NAME,
		dropdownMatchSelectWidth: 500,
		mode: props.multiple ? 'multiple' : undefined,
		disabled: toRef(props, 'disabled', false),
		placeholder: toRef(props, 'placeholder', `请选择部门${props?.onlyDept ? '' : '、人员'}`),
		dropdownClassName: 'dept-emp-select-dropdown',
		onDropdownVisibleChange() {
			if (event) {
				options.open = !options.open
			} else {
				options.open = true
			}
		},
		onChange(values: any) {
			if (props.multiple) {
				options.options.forEach((o: any) => (o.selected = values.includes(o.id)))
				fillSelections(true)
			} else {
				clear()
			}
		}
	})

	const keyword = ref<string>('')
	const empIds = ref<any>([props.empId].flat())
	const deptIds = ref<any>([props.deptId].flat())
	const selections = ref<any>()

	const loadings = reactive({
		load: false
	})

	const emits = defineEmits(['update:empId', 'update:deptId', 'change'])
	const fillSelections = XEUtils.debounce((trigger?: boolean) => {
		const result: any = {
			depts: flatDepts.value.filter((o: any) => o.selected),
			emps: employees.value.filter((o: any) => o.selected)
		}

		empIds.value = result.emps.map((o: any) => o.id)
		deptIds.value = result.depts.map((o: any) => o.id)

		const values = Object.values(result)
			.flat()
			.filter((o: any) => (props.onlyEmp ? empIds.value.includes(o.id) : true))
			.map((o: any) => o[props.multiple ? 'id' : 'name'])

		selections.value = props.multiple ? values : values.join('/') || null

		if (trigger) {
			if (props.multiple) {
				emits('update:empId', empIds.value)
				emits('update:deptId', deptIds.value)
			} else {
				emits('update:empId', empIds.value[0] || null)
				emits('update:deptId', deptIds.value[0] || null)
			}

			emits('change', result)
		}
	}, 0)

	// 部门列表
	const depts = ref<Department[]>([])
	const flatDepts = ref<any[]>([])
	const deptTreeOptions = reactive({
		height: 300,
		checkStrictly: true,
		defaultExpandAll: true,
		checkedKeys: deptIds,
		selectedKeys: deptIds,
		multiple: props.multiple && !props.onlyEmp,
		checkable: props.multiple && !props.onlyEmp,
		fieldNames: {key: 'id', title: 'name', children: 'childList'},
		treeData: computed(() =>
			XEUtils.searchTree(
				depts.value,
				(item: any) => {
					const ids = employees.value.filter(o => o.name?.includes(keyword.value)).map(o => o.deptId)
					return item.name?.includes(keyword.value) || ids.includes(item.id)
				},
				{children: 'childList'}
			)
		),
		onCheck({checked}: any) {
			console.log('dept check')
			flatDepts.value.forEach(o => (o.selected = checked.includes(o.id)))
			if (!props.multiple) {
				employees.value.filter((o: any) => !checked.includes(o.deptId)).forEach((o: any) => (o.selected = false))
			}
			fillSelections(true)
		},
		onSelect(keys: string[]) {
			flatDepts.value.forEach((o: any) => (o.selected = keys.includes(o.id)))
			if (!props.multiple) {
				employees.value.filter((o: any) => !keys.includes(o.deptId)).forEach((o: any) => (o.selected = false))
			}
			fillSelections(true)
		}
	})

	// 员工列表
	const employees = ref<Employee[]>([])
	const filterEmplyees = computed(() => {
		return employees.value.filter((o: any) => {
			return (o.name?.includes(keyword.value) && deptIds.value.includes(o.deptId)) || empIds.value.includes(o.id)
		})
	})
	const empTreeOptions = reactive({
		height: 300,
		checkable: true,
		selectable: false,
		checkedKeys: empIds,
		treeData: filterEmplyees,
		fieldNames: {key: 'id', title: 'name'},
		onCheck(keys: string[], {checked, node}: any) {
			console.log('emp check')
			if (props.multiple) {
				employees.value.forEach((o: any) => (o.selected = keys.includes(o.id)))
			} else {
				employees.value.forEach((o: any) => (o.selected = checked && node.id === o.id))
			}
			fillSelections(true)
		}
	})

	onMounted(async () => {
		loadings.load = true

		const setData = ([{data: deps}, {data: emps}]) => {
				empIds.value = [props.empId].flat()
				deptIds.value = [props.deptId].flat()

				// 部门列表赋值
				if (props.onlyStore) {
					depts.value = XEUtils.filterTree([deps], item => item.isStore, {children: 'childList'})
				} else {
					depts.value = [deps]
				}

				flatDepts.value = XEUtils.toTreeArray(depts.value, {children: 'childList'})
				flatDepts.value.forEach((o: any) => (o.selected = deptIds.value.includes(o.id)))

				// 员工列表赋值
				employees.value = emps
				employees.value.forEach((o: any) => (o.selected = empIds.value.includes(o.id)))

				options.options = flatDepts.value.concat(employees.value)
				startWatch()
			}

		if (props.cache) {
			if (!store.deptOptionData.length) {
				await store.getDeptOptions()
			}
			setData(_.cloneDeep(store.deptOptionData) as any)

			loadings.load = false
			return
		}
		Promise.all([settingApi.getDeptTreeList(), settingApi.getAllEmpList()])
			.then( ([{data: deps}, {data: emps}]) => {
				setData([{data: deps}, {data: emps}])
			})
			.finally(() => (loadings.load = false))
	})

	const clear = () => {
		options.options.forEach((o: any) => (o.selected = false))
		fillSelections(true)
		options.open = false
	}

	const confirm = () => {
		options.open = false
	}

	const startWatch = () => {
		fillSelections()

		watch([() => props.empId, () => props.deptId], () => {
			const ids = [props.empId, props.deptId].flat()

			if (props.deptId === undefined) {
				employees.value.forEach((o: any) => (o.selected = ids.includes(o.id)))
			} else {
				options.options.forEach((o: any) => (o.selected = ids.includes(o.id)))
			}
			fillSelections()
		})
	}

			// 将方法暴露
	defineExpose({
		clear
	})
</script>

<style lang="less">
	.dept-emp-select {
		width: 100%;
	}

	.dept-emp-select-dropdown {
		.dept-emp-search-wrapper {
			padding: 8px 12px;
		}

		.dept-emp-wrapper {
			display: flex;
			min-height: 300px;

			.ant-skeleton {
				padding: 0 12px;
			}

			.ant-tree {
				flex: 2;
			}

			.emp-container {
				flex: 1;
				border-left: 2px solid #ecf0f9;

				.ant-checkbox-wrapper {
					display: flex;
					padding: 4px;
					margin-left: 8px;
				}
			}
		}

		.ant-divider {
			margin: 4px 0;
		}

		.ant-space {
			display: flex;
			justify-content: end;
			padding: 6px 16px;
		}
	}
</style>
